{
 "cells": [
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {
    "cell_id": "9117b11ef6ce47a189467e17c80a4a00",
    "deepnote_app_coordinates": {
     "h": 5,
     "w": 12,
     "x": 0,
     "y": 31
    },
    "deepnote_cell_type": "code",
    "deepnote_to_be_reexecuted": false,
    "execution_millis": 1678,
    "execution_start": 1672344851887,
    "source_hash": "d5d7c02b",
    "tags": []
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "(1000, 16)\n"
     ]
    }
   ],
   "source": [
    "from tqdm import tqdm\n",
    "import numpy as np\n",
    "from matplotlib import pyplot as plt\n",
    "from sklearn.datasets import make_classification\n",
    "from sklearn.tree import DecisionTreeClassifier as DTC\n",
    "from sklearn.model_selection import train_test_split\n",
    "\n",
    "# 创建随机数据集\n",
    "X, y = make_classification(\n",
    "    n_samples=1000, # 数据集大小\n",
    "    n_features=16, # 特征数，即数据维度\n",
    "    n_informative=5, # 有效特征个数\n",
    "    n_redundant=2, # 冗余特征个数，为有效特征的随机线性组合\n",
    "    n_classes=2, # 类别数\n",
    "    flip_y=0.1, # 类别随机的样本个数，该值越大，分类越困难\n",
    "    random_state=0 # 随机种子\n",
    ")\n",
    "\n",
    "print(X.shape)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {
    "cell_id": "09f59f60caa4413199481eac15c08d10",
    "deepnote_app_coordinates": {
     "h": 5,
     "w": 12,
     "x": 0,
     "y": 43
    },
    "deepnote_cell_type": "code",
    "deepnote_to_be_reexecuted": false,
    "execution_millis": 3,
    "execution_start": 1672344859132,
    "id": "D48D6EFE522D416CA560F56280404245",
    "jupyter": {},
    "scrolled": false,
    "slideshow": {
     "slide_type": "slide"
    },
    "source_hash": "b94c010d",
    "tags": []
   },
   "outputs": [],
   "source": [
    "class RandomForest():\n",
    "\n",
    "    def __init__(self, n_trees=10, max_features='sqrt'):\n",
    "        # max_features是DTC的参数，表示结点分裂时随机采样的特征个数\n",
    "        # sqrt代表取全部特征的平方根，None代表取全部特征，log2代表取全部特征的对数\n",
    "        self.n_trees = n_trees\n",
    "        self.oob_score = 0\n",
    "        self.trees = [DTC(max_features=max_features)\n",
    "            for _ in range(n_trees)]\n",
    "\n",
    "    # 用X和y训练模型\n",
    "    def fit(self, X, y):\n",
    "        n_samples, n_features = X.shape\n",
    "        self.n_classes = np.unique(y).shape[0]   \n",
    "        # 集成模型的预测，累加单个模型预测的分类概率，再取较大值作为最终分类\n",
    "        ensemble = np.zeros((n_samples, self.n_classes))\n",
    "            \n",
    "        for tree in self.trees:\n",
    "            # 自举采样，该采样允许重复\n",
    "            idx = np.random.randint(0, n_samples, n_samples)\n",
    "            # 没有被采到的样本\n",
    "            unsampled_mask = np.bincount(idx, minlength=n_samples) == 0\n",
    "            unsampled_idx = np.arange(n_samples)[unsampled_mask]\n",
    "            # 训练当前决策树\n",
    "            tree.fit(X[idx], y[idx])\n",
    "            # 累加决策树对OOB样本的预测\n",
    "            ensemble[unsampled_idx] += tree.predict_proba(X[unsampled_idx])\n",
    "        # 计算OOB分数，由于是分类任务，我们用正确率来衡量\n",
    "        self.oob_score = np.mean(y == np.argmax(ensemble, axis=1))\n",
    "    \n",
    "    # 预测类别\n",
    "    def predict(self, X):\n",
    "        proba = self.predict_proba(X)\n",
    "        return np.argmax(proba, axis=1)\n",
    "    \n",
    "    def predict_proba(self, X):\n",
    "        # 取所有决策树预测概率的平均\n",
    "        ensemble = np.mean([tree.predict_proba(X)\n",
    "            for tree in self.trees], axis=0)\n",
    "        return ensemble\n",
    "    \n",
    "    # 计算正确率\n",
    "    def score(self, X, y):\n",
    "        return np.mean(y == self.predict(X))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {
    "cell_id": "9ade2debbd28433c9195a949f6ef6e7a",
    "deepnote_app_coordinates": {
     "h": 5,
     "w": 12,
     "x": 0,
     "y": 55
    },
    "deepnote_cell_type": "code",
    "deepnote_to_be_reexecuted": false,
    "execution_millis": 19971,
    "execution_start": 1672344862088,
    "id": "B3082D1F8B214B48B0374D31B9DF813F",
    "jupyter": {},
    "scrolled": false,
    "slideshow": {
     "slide_type": "slide"
    },
    "source_hash": "b86f3a",
    "tags": []
   },
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "100%|███████████████████████████████████████| 20/20 [00:21<00:00,  1.07s/it, n_tree=96, train_score=1, oob_score=0.888]\n",
      "100%|███████████████████████████████████████| 20/20 [00:07<00:00,  2.57it/s, n_tree=96, train_score=1, oob_score=0.897]\n"
     ]
    },
    {
     "data": {
      "image/png": "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",
      "text/plain": [
       "<Figure size 640x480 with 1 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "# 算法测试与可视化\n",
    "num_trees = np.arange(1, 101, 5)\n",
    "np.random.seed(0)\n",
    "plt.figure()\n",
    "\n",
    "# bagging算法\n",
    "oob_score = []\n",
    "train_score = []\n",
    "with tqdm(num_trees) as pbar:\n",
    "    for n_tree in pbar:\n",
    "        rf = RandomForest(n_trees=n_tree, max_features=None)\n",
    "        rf.fit(X, y)\n",
    "        train_score.append(rf.score(X, y))\n",
    "        oob_score.append(rf.oob_score)\n",
    "        pbar.set_postfix({\n",
    "            'n_tree': n_tree, \n",
    "            'train_score': train_score[-1], \n",
    "            'oob_score': oob_score[-1]\n",
    "        })\n",
    "plt.plot(num_trees, train_score, color='blue', \n",
    "    label='bagging_train_score')\n",
    "plt.plot(num_trees, oob_score, color='blue', linestyle='-.', \n",
    "    label='bagging_oob_score')\n",
    "\n",
    "# 随机森林算法\n",
    "oob_score = []\n",
    "train_score = []\n",
    "with tqdm(num_trees) as pbar:\n",
    "    for n_tree in pbar:\n",
    "        rf = RandomForest(n_trees=n_tree, max_features='sqrt')\n",
    "        rf.fit(X, y)\n",
    "        train_score.append(rf.score(X, y))\n",
    "        oob_score.append(rf.oob_score)\n",
    "        pbar.set_postfix({\n",
    "            'n_tree': n_tree, \n",
    "            'train_score': train_score[-1], \n",
    "            'oob_score': oob_score[-1]\n",
    "        })\n",
    "plt.plot(num_trees, train_score, color='red', linestyle='--', \n",
    "    label='random_forest_train_score')\n",
    "plt.plot(num_trees, oob_score, color='red', linestyle=':', \n",
    "    label='random_forest_oob_score')\n",
    "\n",
    "plt.ylabel('Score')\n",
    "plt.xlabel('Number of trees')\n",
    "plt.legend()\n",
    "plt.show()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {
    "cell_id": "459eade73df14d3d8699008675468ed5",
    "deepnote_app_coordinates": {
     "h": 5,
     "w": 12,
     "x": 0,
     "y": 67
    },
    "deepnote_cell_type": "code",
    "deepnote_to_be_reexecuted": false,
    "execution_millis": 1634,
    "execution_start": 1672344895308,
    "id": "54C4CC5A64F54A7184C884025AE61640",
    "jupyter": {},
    "scrolled": false,
    "slideshow": {
     "slide_type": "slide"
    },
    "source_hash": "13326553",
    "tags": []
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "bagging： 0.885\n",
      "随机森林： 0.897\n"
     ]
    }
   ],
   "source": [
    "from sklearn.ensemble import BaggingClassifier, RandomForestClassifier\n",
    "\n",
    "bc = BaggingClassifier(n_estimators=100, oob_score=True, random_state=0)\n",
    "bc.fit(X, y)\n",
    "print('bagging：', bc.oob_score_)\n",
    "\n",
    "rfc = RandomForestClassifier(n_estimators=100, max_features='sqrt', \n",
    "    oob_score=True, random_state=0)\n",
    "rfc.fit(X, y)\n",
    "print('随机森林：', rfc.oob_score_)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {
    "cell_id": "88173194e475444188774c689c9694bc",
    "deepnote_app_coordinates": {
     "h": 5,
     "w": 12,
     "x": 0,
     "y": 91
    },
    "deepnote_cell_type": "code",
    "deepnote_to_be_reexecuted": false,
    "execution_millis": 4,
    "execution_start": 1672344906149,
    "id": "6499FABC7DFD4BB08BCA4D31BDB1272E",
    "jupyter": {},
    "scrolled": false,
    "slideshow": {
     "slide_type": "slide"
    },
    "source_hash": "e7af5132",
    "tags": []
   },
   "outputs": [],
   "source": [
    "from sklearn.model_selection import KFold\n",
    "from sklearn.base import clone\n",
    "\n",
    "# 堆垛分类器，继承sklearn中的集成分类器基类EnsembleClassifier\n",
    "class StackingClassifier():\n",
    "\n",
    "    def __init__(\n",
    "        self, \n",
    "        classifiers, # 基础分类器\n",
    "        meta_classifier, # 元分类器\n",
    "        concat_feature=False, # 是否将原始数据拼接在新数据上\n",
    "        kfold=5 # K折交叉验证\n",
    "    ):\n",
    "        self.classifiers = classifiers\n",
    "        self.meta_classifier = meta_classifier\n",
    "        self.concat_feature = concat_feature\n",
    "        self.kf = KFold(n_splits=kfold)\n",
    "        # 为了在测试时计算平均，我们需要保留每个分类器\n",
    "        self.k_fold_classifiers = []\n",
    "        \n",
    "    def fit(self, X, y):\n",
    "        # 用X和y训练基础分类器和元分类器\n",
    "        n_samples, n_features = X.shape\n",
    "        self.n_classes = np.unique(y).shape[0]\n",
    "        \n",
    "        if self.concat_feature:\n",
    "            features = X\n",
    "        else:\n",
    "            features = np.zeros((n_samples, 0))\n",
    "        for classifier in self.classifiers:\n",
    "            self.k_fold_classifiers.append([])\n",
    "            # 训练每个基础分类器\n",
    "            predict_proba = np.zeros((n_samples, self.n_classes))\n",
    "            for train_idx, test_idx in self.kf.split(X):\n",
    "                # 交叉验证\n",
    "                clf = clone(classifier)\n",
    "                clf.fit(X[train_idx], y[train_idx])\n",
    "                predict_proba[test_idx] = clf.predict_proba(X[test_idx])\n",
    "                self.k_fold_classifiers[-1].append(clf)\n",
    "            features = np.concatenate([features, predict_proba], axis=-1)\n",
    "        # 训练元分类器\n",
    "        self.meta_classifier.fit(features, y)\n",
    "    \n",
    "    def _get_features(self, X):\n",
    "        # 计算输入X的特征\n",
    "        if self.concat_feature:\n",
    "            features = X\n",
    "        else:\n",
    "            features = np.zeros((X.shape[0], 0))\n",
    "        for k_classifiers in self.k_fold_classifiers:\n",
    "            k_feat = np.mean([clf.predict_proba(X)\n",
    "                for clf in k_classifiers], axis=0)\n",
    "            features = np.concatenate([features, k_feat], axis=-1)\n",
    "        return features\n",
    "    \n",
    "    def predict(self, X):\n",
    "        return self.meta_classifier.predict(self._get_features(X))\n",
    "        \n",
    "    def score(self, X, y):\n",
    "        return self.meta_classifier.score(self._get_features(X), y)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {
    "cell_id": "5b6f59428c12428c91270439859e1ddd",
    "deepnote_app_coordinates": {
     "h": 5,
     "w": 12,
     "x": 0,
     "y": 103
    },
    "deepnote_cell_type": "code",
    "deepnote_to_be_reexecuted": false,
    "execution_millis": 1150,
    "execution_start": 1672344909280,
    "id": "53A5CC533DF74E7181CA011806310F4C",
    "jupyter": {},
    "scrolled": false,
    "slideshow": {
     "slide_type": "slide"
    },
    "source_hash": "e55f08ba",
    "tags": []
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "随机森林： 0.895\n",
      "KNN： 0.9\n",
      "逻辑斯谛回归： 0.855\n",
      "Stacking分类器： 0.91\n",
      "带原始特征的Stacking分类器： 0.905\n"
     ]
    }
   ],
   "source": [
    "from sklearn.linear_model import LogisticRegression as LR\n",
    "from sklearn.ensemble import RandomForestClassifier as RFC\n",
    "from sklearn.neighbors import KNeighborsClassifier as KNC\n",
    "\n",
    "# 划分训练集和测试集\n",
    "X_train, X_test, y_train, y_test = \\\n",
    "    train_test_split(X, y, test_size=0.2, random_state=0)\n",
    "\n",
    "# 基础分类器\n",
    "rf = RFC(n_estimators=10, max_features='sqrt', \n",
    "    random_state=0).fit(X_train, y_train)\n",
    "knc = KNC().fit(X_train, y_train)\n",
    "# multi_class='ovr'表示二分类问题\n",
    "lr = LR(solver='liblinear', multi_class='ovr', \n",
    "    random_state=0).fit(X_train, y_train)\n",
    "print('随机森林：', rf.score(X_test, y_test))\n",
    "print('KNN：', knc.score(X_test, y_test))\n",
    "print('逻辑斯谛回归：', lr.score(X_test, y_test))\n",
    "# 元分类器\n",
    "meta_lr = LR(solver='liblinear', multi_class='ovr', random_state=0)\n",
    "\n",
    "sc = StackingClassifier([rf, knc, lr], meta_lr, concat_feature=False)\n",
    "sc.fit(X_train, y_train)\n",
    "print('Stacking分类器：', sc.score(X_test, y_test))\n",
    "\n",
    "# 带原始特征的stacking分类器\n",
    "sc_concat = StackingClassifier([rf, knc, lr], meta_lr, concat_feature=True)\n",
    "sc_concat.fit(X_train, y_train)\n",
    "print('带原始特征的Stacking分类器：', sc_concat.score(X_test, y_test))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "metadata": {
    "cell_id": "7ef6eb1f941c42c7919ef5dc3781aa25",
    "deepnote_app_coordinates": {
     "h": 5,
     "w": 12,
     "x": 0,
     "y": 157
    },
    "deepnote_cell_type": "code",
    "deepnote_to_be_reexecuted": false,
    "execution_millis": 10837,
    "execution_start": 1672344981631,
    "source_hash": "d405497b",
    "tags": []
   },
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "100%|██████████████████████████████████████████████████████████████████████████████████| 20/20 [00:28<00:00,  1.40s/it]\n"
     ]
    },
    {
     "data": {
      "image/png": "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vRIREemMXpM6Pz8/xMfHY/r06YiOjkbDhg2xe/dueTVrdHR0npp1KpUK27Ztw8KFC/O9pre3NzZt2oRvv/0WkydPRs2aNREQEICWLVsW+fuhQho7FnByAvr21XckREREpZ5e69SVVKxTR0REREXNYOrUEREREZHuMKmj4hcZCcyaBYSH6zsSIiIig8GkjopfQADw7bfA//6n70iIiIgMBpM6Kn4sOExERKRzTOqoeN26BZw7BxgZAX366DsaIiIig8GkjorXli3Sv+3bA5Uq6TcWIiIiA8KkjopXztArCw4TERHpFJM6Kj43bgAXLgBKJdCrl76jISIiMih63VGCypirVwFra8DHB6hQQd/REBERGRQmdVR8evYEYmOBR4/0HQkREZHB4fArFS8LC8DFRd9REBERGRwmdVQ84uMBbjNMRERUZJjUUfFo2xaoXx+4eFHfkRARERkkzqmjonflChAaCpiaAm5u+o6GiIjIILGnjopeTm26Ll0AOzv9xkJERGSgmNRR0RICCAiQPuZer0REREWGSR0VrUuXgPBwwMwMePddfUdDRERksJjUUdHK6aV7+23Axka/sRARERkwJnVUdITInU/HoVciIqIixdWvVHSEABYvBrZuBbp103c0REREBo1JHRUdIyNpxWuXLvqOhIiIyOBx+JWIiIjIADCpo6IREgJ89RXw77/6joSIiKhM4PArFY0//gDmzgWiooCNG/UdDRERkcFjTx3pnkbDVa9ERETFjD11pHunT0s9dNbWQNeu+o6GiAyARqNBZmamvsMgKjRTU1MYGRVPHxqTOtK9nILDPXoA5ub6jYWISr3MzExERERAo9HoOxSiQjMyMkL16tVhampa5PdiUke6pdEAW7ZIH/v56TcWIir1hBCIjo6GUqlEtWrViq3Hg0gXNBoNHjx4gOjoaLi4uEChUBTp/ZjUkW4dPw48eADY2QGdOuk7GiIq5bKzs5GamorKlSvD0tJS3+EQFVrFihXx4MEDZGdnw8TEpEjvxT95SLeio4GKFYGePQEzM31HQ0SlnFqtBoBiGboiKgo537s538tFiT11pFv9+gG9ewOJifqOhIgMSFEPWxEVleL83mVPXVly4waQklL09zE2BsqXL/r7EBHRS7Vr1w5jx47VdxhUDJjUGbK//wZu38597ucH2NsDPj7A118D+/YBycm6u9/t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",
      "text/plain": [
       "<Figure size 640x480 with 1 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "from sklearn.ensemble import AdaBoostClassifier\n",
    "\n",
    "# 初始化stump\n",
    "stump = DTC(max_depth=1, min_samples_leaf=1, random_state=0)\n",
    "\n",
    "# 弱分类器个数\n",
    "M = np.arange(1, 101, 5)\n",
    "bg_score = []\n",
    "rf_score = []\n",
    "dsc_ada_score = []\n",
    "real_ada_score = []\n",
    "plt.figure()\n",
    "\n",
    "with tqdm(M) as pbar:\n",
    "    for m in pbar:\n",
    "        # bagging算法\n",
    "        bc = BaggingClassifier(estimator=stump, \n",
    "            n_estimators=m, random_state=0)\n",
    "        bc.fit(X_train, y_train)\n",
    "        bg_score.append(bc.score(X_test, y_test))\n",
    "        # 随机森林算法\n",
    "        rfc = RandomForestClassifier(n_estimators=m, max_depth=1, \n",
    "            min_samples_leaf=1, random_state=0)\n",
    "        rfc.fit(X_train, y_train)\n",
    "        rf_score.append(rfc.score(X_test, y_test))\n",
    "        # 离散 AdaBoost，SAMME是分步加性模型（stepwise additive model）的缩写\n",
    "        dsc_adaboost = AdaBoostClassifier(estimator=stump, \n",
    "            n_estimators=m, algorithm='SAMME', random_state=0)\n",
    "        dsc_adaboost.fit(X_train, y_train)\n",
    "        dsc_ada_score.append(dsc_adaboost.score(X_test, y_test))\n",
    "        # 实 AdaBoost，SAMME.R表示弱分类器输出实数\n",
    "        real_adaboost = AdaBoostClassifier(estimator=stump, \n",
    "            n_estimators=m, algorithm='SAMME.R', random_state=0)\n",
    "        real_adaboost.fit(X_train, y_train)\n",
    "        real_ada_score.append(real_adaboost.score(X_test, y_test))\n",
    "\n",
    "# 绘图\n",
    "plt.plot(M, bg_score, color='blue', label='Bagging')\n",
    "plt.plot(M, rf_score, color='red', ls='--', label='Random Forest')\n",
    "plt.plot(M, dsc_ada_score, color='green', ls='-.', label='Discrete AdaBoost')\n",
    "plt.plot(M, real_ada_score, color='purple', ls=':', label='Real AdaBoost')\n",
    "plt.xlabel('Number of trees')\n",
    "plt.ylabel('Test score')\n",
    "plt.legend()\n",
    "plt.tight_layout()\n",
    "plt.savefig('output_26_1.png')\n",
    "plt.savefig('output_26_1.pdf')\n",
    "plt.show()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "metadata": {
    "cell_id": "84372d45c1f448d2adf5f1342a31f268",
    "deepnote_app_coordinates": {
     "h": 5,
     "w": 12,
     "x": 0,
     "y": 187
    },
    "deepnote_cell_type": "code",
    "deepnote_to_be_reexecuted": false,
    "execution_millis": 3642,
    "execution_start": 1672346468352,
    "source_hash": "83a6e9d8",
    "tags": []
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Requirement already satisfied: xgboost in f:\\anaconda3\\lib\\site-packages (1.7.3)\n",
      "Requirement already satisfied: numpy in f:\\anaconda3\\lib\\site-packages (from xgboost) (1.21.5)\n",
      "Requirement already satisfied: scipy in f:\\anaconda3\\lib\\site-packages (from xgboost) (1.9.1)\n"
     ]
    }
   ],
   "source": [
    "# 安装并导入xgboost库\n",
    "!pip install xgboost\n",
    "import xgboost as xgb\n",
    "from sklearn.datasets import make_friedman1\n",
    "from sklearn.neighbors import KNeighborsRegressor\n",
    "from sklearn.linear_model import LinearRegression\n",
    "from sklearn.tree import DecisionTreeRegressor\n",
    "from sklearn.ensemble import BaggingRegressor, RandomForestRegressor, \\\n",
    "    StackingRegressor, AdaBoostRegressor\n",
    "\n",
    "# 生成回归数据集\n",
    "reg_X, reg_y = make_friedman1(\n",
    "    n_samples=2000, # 样本数目\n",
    "    n_features=100, # 特征数目\n",
    "    noise=0.5, # 噪声的标准差\n",
    "    random_state=0 # 随机种子\n",
    ")\n",
    "\n",
    "# 划分训练集与测试集\n",
    "reg_X_train, reg_X_test, reg_y_train, reg_y_test = \\\n",
    "    train_test_split(reg_X, reg_y, test_size=0.2, random_state=0)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "metadata": {
    "cell_id": "ed114fef61b4434eae7f106e53f8e79a",
    "deepnote_app_coordinates": {
     "h": 5,
     "w": 12,
     "x": 0,
     "y": 193
    },
    "deepnote_cell_type": "code",
    "deepnote_to_be_reexecuted": false,
    "execution_millis": 7710,
    "execution_start": 1672346475053,
    "source_hash": "4848b46c",
    "tags": []
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "XGBoost：1.652\n",
      "KNN：4.471\n",
      "线性回归：2.525\n",
      "Bagging：4.042\n",
      "随机森林：4.514\n",
      "Stacking：2.231\n",
      "带输入特征的Stacking：2.288\n",
      "AdaBoost：3.116\n"
     ]
    }
   ],
   "source": [
    "def rmse(regressor):\n",
    "    # 计算regressor在测试集上的RMSE\n",
    "    y_pred = regressor.predict(reg_X_test)\n",
    "    return np.sqrt(np.mean((y_pred - reg_y_test) ** 2))\n",
    "\n",
    "# XGBoost回归树\n",
    "xgbr = xgb.XGBRegressor(\n",
    "    n_estimators=100, # 弱分类器数目\n",
    "    max_depth=1, # 决策树最大深度\n",
    "    learning_rate=0.5, # 学习率\n",
    "    gamma=0.0, # 对决策树叶结点数目的惩罚系数，当弱分类器为stump时不起作用\n",
    "    reg_lambda=0.1, # L2正则化系数\n",
    "    subsample=0.5, # 与随机森林类似，表示采样特征的比例\n",
    "    objective='reg:squarederror', # MSE损失函数\n",
    "    eval_metric='rmse', # 用RMSE作为评价指标\n",
    "    random_state=0 # 随机种子\n",
    ")\n",
    "\n",
    "xgbr.fit(reg_X_train, reg_y_train)\n",
    "print(f'XGBoost：{rmse(xgbr):.3f}')\n",
    "\n",
    "# KNN回归\n",
    "knnr = KNeighborsRegressor(n_neighbors=5).fit(reg_X_train, reg_y_train)\n",
    "print(f'KNN：{rmse(knnr):.3f}')\n",
    "\n",
    "# 线性回归\n",
    "lnr = LinearRegression().fit(reg_X_train, reg_y_train)\n",
    "print(f'线性回归：{rmse(lnr):.3f}')\n",
    "\n",
    "# bagging\n",
    "stump_reg = DecisionTreeRegressor(max_depth=1, \n",
    "    min_samples_leaf=1, random_state=0)\n",
    "bcr = BaggingRegressor(estimator=stump_reg, \n",
    "    n_estimators=100, random_state=0)\n",
    "bcr.fit(reg_X_train, reg_y_train)\n",
    "print(f'Bagging：{rmse(bcr):.3f}')\n",
    "\n",
    "# 随机森林\n",
    "rfr = RandomForestRegressor(n_estimators=100, max_depth=1, \n",
    "    max_features='sqrt', random_state=0)\n",
    "rfr.fit(reg_X_train, reg_y_train)\n",
    "print(f'随机森林：{rmse(rfr):.3f}')\n",
    "\n",
    "# 堆垛，默认元学习器为带L2正则化约束的线性回归\n",
    "stkr = StackingRegressor(estimators=[\n",
    "    ('knn', knnr), \n",
    "    ('ln', lnr), \n",
    "    ('rf', rfr)\n",
    "])\n",
    "stkr.fit(reg_X_train, reg_y_train)\n",
    "print(f'Stacking：{rmse(stkr):.3f}')\n",
    "\n",
    "# 带有输入特征的堆垛\n",
    "stkr_pt = StackingRegressor(estimators=[\n",
    "    ('knn', knnr), \n",
    "    ('ln', lnr), \n",
    "    ('rf', rfr)\n",
    "], passthrough=True)\n",
    "stkr_pt.fit(reg_X_train, reg_y_train)\n",
    "print(f'带输入特征的Stacking：{rmse(stkr_pt):.3f}')\n",
    "\n",
    "# AdaBoost，回归型AdaBoost只有连续型，没有离散型\n",
    "abr = AdaBoostRegressor(estimator=stump_reg, n_estimators=100, \n",
    "    learning_rate=1.5, loss='square', random_state=0)\n",
    "abr.fit(reg_X_train, reg_y_train)\n",
    "print(f'AdaBoost：{rmse(abr):.3f}')"
   ]
  }
 ],
 "metadata": {
  "deepnote": {},
  "deepnote_app_layout": "article",
  "deepnote_execution_queue": [],
  "deepnote_notebook_id": "b15e3cce624d49d49495fc57a07bc4e4",
  "kernelspec": {
   "display_name": "Python 3 (ipykernel)",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.9.13"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 1
}
